home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / cpp / part05 < prev   
Encoding:
Internet Message Format  |  1990-01-18  |  36.3 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i026: cpp - a c preprocessor with some ANSI features, Part05/05
  5. Message-ID: <11034@xanth.cs.odu.edu>
  6. Date: 18 Jan 90 00:23:22 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  9. Lines: 1223
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11.  
  12. Submitted-by: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
  13. Posting-number: Volume 90, Issue 026
  14. Archive-name: unix/cpp/part05
  15.  
  16. #!/bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 5 (of 5)."
  23. # Contents:  Cpp6.c
  24. # Wrapped by tadguy@xanth on Wed Jan 17 19:17:38 1990
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'Cpp6.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'Cpp6.c'\"
  28. else
  29. echo shar: Extracting \"'Cpp6.c'\" \(33823 characters\)
  30. sed "s/^X//" >'Cpp6.c' <<'END_OF_FILE'
  31. X/*
  32. X *                C P P 6 . C
  33. X *        S u p p o r t    R o u t i n e s
  34. X *
  35. X * Edit History
  36. X * 25-May-84 MM     Added 8-bit support to type table.
  37. X * 30-May-84 ARF    sharp() should output filename in quotes
  38. X * 02-Aug-84 MM     Newline and #line hacking.  sharp() now in cpp1.c
  39. X * 31-Aug-84 MM     USENET net.sources release
  40. X * 11-Sep-84 ado/MM    Keepcomments, also line number pathological
  41. X * 12-Sep-84 ado/MM    bug if comment changes to space and we unget later.
  42. X * 03-Oct-84 gkr/MM    Fixed scannumber bug for '.e' (as in struct.element).
  43. X * 04-Oct-84 MM     Added ungetstring() for token concatenation
  44. X * 08-Oct-84 MM     Yet another attack on number scanning
  45. X * 31-Oct-84 ado    Parameterized $ in identifiers
  46. X *  2-Nov-84 MM     Token concatenation is messier than I thought
  47. X *  6-Dec-84 MM     \<nl> is everywhere invisible.
  48. X * 21-Oct-85 RMS    Rename `token' to `tokenbuf'.
  49. X *            Dynamically allocate it, and make it as big as needed.
  50. X * 23-Oct-85 RMS    Fix bugs storing into tokenbuf as it gets bigger.
  51. X *            Change error msg to  cpp: "FILE", line LINE: MSG
  52. X * 24-Oct-85 RMS    Turn off warnings about / then * inside a comment.
  53. X * 16-Mar-86 FNF    Incorporate macro based C debugging package.
  54. X *            Port to Commodore Amiga.
  55. X * 20-Aug-88 Ois    Added time routines (or actually deleted stubs).
  56. X * 20-Aug-88 Ois    Changed handling of token following ## to match Cpp4.
  57. X */
  58. X
  59. X#include    <stdio.h>
  60. X#include    <ctype.h>
  61. X#include    "cppdef.h"
  62. X#include    "cpp.h"
  63. X
  64. X/*
  65. X * skipnl()     skips over input text to the end of the line.
  66. X * skipws()     skips over "whitespace" (spaces or tabs), but
  67. X *        not skip over the end of the line.  It skips over
  68. X *        TOK_SEP, however (though that shouldn't happen).
  69. X * scanid()     reads the next token (C identifier) into tokenbuf.
  70. X *        The caller has already read the first character of
  71. X *        the identifier.  Unlike macroid(), the token is
  72. X *        never expanded.
  73. X * macroid()    reads the next token (C identifier) into tokenbuf.
  74. X *        If it is a #defined macro, it is expanded, and
  75. X *        macroid() returns TRUE, otherwise, FALSE.
  76. X * catenate()   Does the dirty work of token concatenation, TRUE if it did.
  77. X * scanstring() Reads a string from the input stream, calling
  78. X *        a user-supplied function for each character.
  79. X *        This function may be output() to write the
  80. X *        string to the output file, or save() to save
  81. X *        the string in the work buffer.
  82. X * scannumber() Reads a C numeric constant from the input stream,
  83. X *        calling the user-supplied function for each
  84. X *        character.  (output() or save() as noted above.)
  85. X * save()       Save one character in the work[] buffer.
  86. X * savestring() Saves a string in malloc() memory.
  87. X * getfile()    Initialize a new FILEINFO structure, called when
  88. X *        #include opens a new file, or a macro is to be
  89. X *        expanded.
  90. X * getmem()     Get a specified number of bytes from malloc memory.
  91. X * output()     Write one character to stdout (calling putchar) --
  92. X *        implemented as a function so its address may be
  93. X *        passed to scanstring() and scannumber().
  94. X * lookid()     Scans the next token (identifier) from the input
  95. X *        stream.  Looks for it in the #defined symbol table.
  96. X *        Returns a pointer to the definition, if found, or NULL
  97. X *        if not present.  The identifier is stored in tokenbuf.
  98. X * defnedel()   Define enter/delete subroutine.  Updates the
  99. X *        symbol table.
  100. X * get()        Read the next byte from the current input stream,
  101. X *        handling end of (macro/file) input and embedded
  102. X *        comments appropriately.  Note that the global
  103. X *        instring is -- essentially -- a parameter to get().
  104. X * cget()       Like get(), but skip over TOK_SEP.
  105. X * unget()      Push last gotten character back on the input stream.
  106. X * cerror(), cwarn(), cfatal(), cierror(), ciwarn()
  107. X *        These routines format an print messages to the user.
  108. X *        cerror & cwarn take a format and a single string argument.
  109. X *        cierror & ciwarn take a format and a single int (char) argument.
  110. X *        cfatal takes a format and a single string argument.
  111. X */
  112. X
  113. X/*
  114. X * This table must be rewritten for a non-Ascii machine.
  115. X *
  116. X * Note that several "non-visible" characters have special meaning:
  117. X * Hex 1C QUOTE_PARM --a flag for # stringifying
  118. X * Hex 1D DEF_MAGIC -- a flag to prevent #define recursion.
  119. X * Hex 1E TOK_SEP   -- a delimiter for ## token concatenation
  120. X * Hex 1F COM_SEP   -- a zero-width whitespace for comment concatenation
  121. X */
  122. X#if TOK_SEP != 0x1E || COM_SEP != 0x1F || DEF_MAGIC != 0x1D
  123. X    << error type table isn't correct >>
  124. X#endif
  125. X
  126. X#if OK_DOLLAR
  127. X#define DOL    LET
  128. X#else
  129. X#define DOL    000
  130. X#endif
  131. X
  132. Xchar type[256] = {        /* Character type codes    Hex        */
  133. X   END,   000,     000,    000,   000,   000,   000,   000, /* 00        */
  134. X   000,   SPA,     000,    000,   000,   000,   000,   000, /* 08        */
  135. X   000,   000,     000,    000,   000,   000,   000,   000, /* 10        */
  136. X   000,   000,     000,    000,   000,   LET,   000,   SPA, /* 18        */
  137. X   SPA,OP_NOT,     QUO,    000,   DOL,OP_MOD,OP_AND,   QUO, /* 20    !"#$%&' */
  138. XOP_LPA,OP_RPA,OP_MUL,OP_ADD,   000,OP_SUB,   DOT,OP_DIV, /* 28 ()*+,-./ */
  139. X   DIG,   DIG,     DIG,    DIG,   DIG,   DIG,   DIG,   DIG, /* 30 01234567 */
  140. X   DIG,   DIG,OP_COL,    000, OP_LT, OP_EQ, OP_GT,OP_QUE, /* 38 89:;<=>? */
  141. X   000,   LET,     LET,    LET,   LET,   LET,   LET,   LET, /* 40 @ABCDEFG */
  142. X   LET,   LET,     LET,    LET,   LET,   LET,   LET,   LET, /* 48 HIJKLMNO */
  143. X   LET,   LET,     LET,    LET,   LET,   LET,   LET,   LET, /* 50 PQRSTUVW */
  144. X   LET,   LET,     LET,    000,   BSH,   000,OP_XOR,   LET, /* 58 XYZ[\]^_ */
  145. X   000,   LET,     LET,    LET,   LET,   LET,   LET,   LET, /* 60 `abcdefg */
  146. X   LET,   LET,     LET,    LET,   LET,   LET,   LET,   LET, /* 68 hijklmno */
  147. X   LET,   LET,     LET,    LET,   LET,   LET,   LET,   LET, /* 70 pqrstuvw */
  148. X   LET,   LET,     LET,    000, OP_OR,   000,OP_NOT,   000, /* 78 xyz{|}~    */
  149. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  150. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  151. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  152. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  153. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  154. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  155. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  156. X   000,   000,     000,    000,   000,   000,   000,   000, /*   80 .. FF    */
  157. X};
  158. X
  159. Xskipnl()
  160. X/*
  161. X * Skip to the end of the current input line.
  162. X */
  163. X{
  164. X    register int        c;
  165. X
  166. X    DBUG_ENTER ("skipnl");
  167. X    do {                /* Skip to newline    */
  168. X        c = get();
  169. X    } while (c != '\n' && c != EOF_CHAR);
  170. X    DBUG_VOID_RETURN;
  171. X}
  172. X
  173. Xint
  174. Xskipws()
  175. X/*
  176. X * Skip over whitespace
  177. X */
  178. X{
  179. X    register int        c;
  180. X
  181. X    DBUG_ENTER ("skipws");
  182. X    do {                /* Skip whitespace    */
  183. X        c = get();
  184. X#if COMMENT_INVISIBLE
  185. X    } while (type[c] == SPA || c == COM_SEP);
  186. X#else
  187. X    } while (type[c] == SPA);
  188. X#endif
  189. X    DBUG_RETURN (c);
  190. X}
  191. X
  192. Xscanid(c)
  193. Xregister int    c;                /* First char of id    */
  194. X/*
  195. X * Get the next token (an id) into the token buffer.
  196. X * Note: this code is duplicated in lookid().
  197. X * Change one, change both.
  198. X */
  199. X{
  200. X    register int ct;
  201. X
  202. X    DBUG_ENTER ("scanid");
  203. X    if (c == DEF_MAGIC)                     /* Eat the magic token  */
  204. X        c = get();                          /* undefiner.           */
  205. X    ct = 0;
  206. X    do
  207. X      {
  208. X        if (ct == tokenbsize)
  209. X#ifdef amiga
  210. X        /*
  211. X         * Duplicate the action of incmem, which grows the area
  212. X         * to the new size, reallocating and copying if necessary.
  213. X         * The disadvantage of this emulation is that the copy is
  214. X         * always done because we have no realloc().
  215. X         */
  216. X          {
  217. X         extern char *malloc ();
  218. X         extern char *memcpy ();
  219. X         char *new = malloc ((unsigned) (1 + (tokenbsize *= 2)));
  220. X         if (new == NULL) {
  221. X            cfatal("Out of memory", NULLST);
  222. X         } else {
  223. X            memcpy (new, tokenbuf, ct);
  224. X            free (tokenbuf);
  225. X            tokenbuf = new;
  226. X         }
  227. X          }
  228. X#else
  229. X          tokenbuf = incmem (tokenbuf, 1 + (tokenbsize *= 2));
  230. X#endif
  231. X        tokenbuf[ct++] = c;
  232. X        c = get();
  233. X      }
  234. X    while (type[c] == LET || type[c] == DIG);
  235. X    unget();
  236. X    tokenbuf[ct] = EOS;
  237. X    DBUG_VOID_RETURN;
  238. X}
  239. X
  240. Xint
  241. Xmacroid(c)
  242. Xregister int        c;
  243. X/*
  244. X * If c is a letter, scan the id.  if it's #defined, expand it and scan
  245. X * the next character and try again.
  246. X *
  247. X * Else, return the character.    If type[c] is a LET, the token is in tokenbuf.
  248. X */
  249. X{
  250. X    register DEFBUF *dp;
  251. X
  252. X    DBUG_ENTER ("macroid");
  253. X    if (infile != NULL && infile->fp != NULL)
  254. X        recursion = 0;
  255. X    while (type[c] == LET && (dp = lookid(c)) != NULL) {
  256. X        expand(dp);
  257. X        c = get();
  258. X    }
  259. X    DBUG_RETURN (c);
  260. X}
  261. X
  262. Xint
  263. Xcatenate()
  264. X/*
  265. X * A token was just read (via macroid).
  266. X * If the next character is TOK_SEP, concatenate the next token
  267. X * return TRUE -- which should recall macroid after refreshing
  268. X * macroid's argument.  If it is not TOK_SEP, unget() the character
  269. X * and return FALSE.
  270. X */
  271. X{
  272. X#if OK_CONCAT
  273. X    register int        c;
  274. X    register char        *token1;
  275. X    int            save();
  276. X#endif
  277. X
  278. X    DBUG_ENTER ("catenate");
  279. X#if OK_CONCAT
  280. X    if (get() != TOK_SEP) {                 /* Token concatenation  */
  281. X        unget();
  282. X        DBUG_RETURN (FALSE);
  283. X    }
  284. X    else {
  285. X        token1 = savestring(tokenbuf);      /* Save first token     */
  286. X        c = macroid(get());                 /* Scan next token      */
  287. X        switch(type[c]) {                   /* What was it?         */
  288. X        case LET:                /* An identifier, ...    */
  289. X        if (strlen(token1) + strlen(tokenbuf) >= NWORK)
  290. X            cfatal("work buffer overflow doing %s ##", token1);
  291. X        sprintf(work, "%s%s", token1, tokenbuf);
  292. X        break;
  293. X
  294. X        case DIG:                /* A number        */
  295. X        case DOT:                /* Or maybe a float    */
  296. X        strcpy(work, token1);
  297. X        workp = work + strlen(work);
  298. X#if 0
  299. X        do {
  300. X            save(c);
  301. X        } while ((c = get()) != TOK_SEP);
  302. X#else
  303. X        scannumber(c, save);
  304. X#endif
  305. X        save(EOS);
  306. X        break;
  307. X
  308. X        default:                /* An error, ...    */
  309. X        if (isprint(c))
  310. X            cierror("Strange character '%c' after ##", c);
  311. X        else
  312. X            cierror("Strange character (%d.) after ##", c);
  313. X        strcpy(work, token1);
  314. X        unget();
  315. X        break;
  316. X        }
  317. X        /*
  318. X         * work has the concatenated token and token1 has
  319. X         * the first token (no longer needed).  Unget the
  320. X         * new (concatenated) token after freeing token1.
  321. X         * Finally, setup to read the new token.
  322. X         */
  323. X        free(token1);                       /* Free up memory       */
  324. X        ungetstring(work);                  /* Unget the new thing, */
  325. X        DBUG_RETURN (TRUE);
  326. X    }
  327. X#else
  328. X    DBUG_RETURN (FALSE);                    /* Not supported        */
  329. X#endif
  330. X}
  331. X
  332. Xint
  333. Xscanstring(delim, outfun)
  334. Xregister int    delim;            /* ' or "                       */
  335. Xint        (*outfun)();            /* Output function              */
  336. X/*
  337. X * Scan off a string.  Warning if terminated by newline or EOF.
  338. X * outfun() outputs the character -- to a buffer if in a macro.
  339. X * TRUE if ok, FALSE if error.
  340. X */
  341. X{
  342. X    register int        c;
  343. X
  344. X    DBUG_ENTER ("scanstring");
  345. X    instring = TRUE;        /* Don't strip comments         */
  346. X    (*outfun)(delim);
  347. X    while ((c = get()) != delim
  348. X         && c != '\n'
  349. X         && c != EOF_CHAR) {
  350. X        (*outfun)(c);
  351. X        if (c == '\\')
  352. X        (*outfun)(get());
  353. X    }
  354. X    instring = FALSE;
  355. X    if (c == delim) {
  356. X        (*outfun)(c);
  357. X        DBUG_RETURN (TRUE);
  358. X    }
  359. X    else {
  360. X        cerror("Unterminated string", NULLST);
  361. X        unget();
  362. X        DBUG_RETURN (FALSE);
  363. X    }
  364. X}
  365. X
  366. Xscannumber(c, outfun)
  367. Xregister int    c;                /* First char of number */
  368. Xregister int    (*outfun)();                    /* Output/store func    */
  369. X/*
  370. X * Process a number.  We know that c is from 0 to 9 or dot.
  371. X * Algorithm from Dave Conroy's Decus C.
  372. X */
  373. X{
  374. X    register int    radix;            /* 8, 10, or 16     */
  375. X    int        expseen;        /* 'e' seen in floater  */
  376. X    int        signseen;        /* '+' or '-' seen      */
  377. X    int        octal89;        /* For bad octal test    */
  378. X    int        dotflag;        /* TRUE if '.' was seen */
  379. X
  380. X    DBUG_ENTER ("scannumber");
  381. X    expseen = FALSE;            /* No exponent seen yet */
  382. X    signseen = TRUE;            /* No +/- allowed yet    */
  383. X    octal89 = FALSE;            /* No bad octal yet    */
  384. X    radix = 10;                /* Assume decimal    */
  385. X    if ((dotflag = (c == '.')) != FALSE) {  /* . something?         */
  386. X        (*outfun)('.');                     /* Always out the dot   */
  387. X        if (type[(c = get())] != DIG) {     /* If not a float numb, */
  388. X        unget();                        /* Rescan strange char  */
  389. X        DBUG_VOID_RETURN;        /* All done for now    */
  390. X        }
  391. X    }                    /* End of float test    */
  392. X    else if (c == '0') {                    /* Octal or hex?        */
  393. X        (*outfun)(c);                       /* Stuff initial zero   */
  394. X        radix = 8;                /* Assume it's octal    */
  395. X        c = get();                          /* Look for an 'x'      */
  396. X        if (c == 'x' || c == 'X') {         /* Did we get one?      */
  397. X        radix = 16;            /* Remember new radix    */
  398. X        (*outfun)(c);                   /* Stuff the 'x'        */
  399. X        c = get();                      /* Get next character   */
  400. X        }
  401. X    }
  402. X    for (;;) {                              /* Process curr. char.  */
  403. X        /*
  404. X         * Note that this algorithm accepts "012e4" and "03.4"
  405. X         * as legitimate floating-point numbers.
  406. X         */
  407. X        if (radix != 16 && (c == 'e' || c == 'E')) {
  408. X        if (expseen)                    /* Already saw 'E'?     */
  409. X            break;            /* Exit loop, bad nbr.    */
  410. X        expseen = TRUE;         /* Set exponent seen    */
  411. X        signseen = FALSE;        /* We can read '+' now  */
  412. X        radix = 10;            /* Decimal exponent    */
  413. X        }
  414. X        else if (radix != 16 && c == '.') {
  415. X        if (dotflag)                    /* Saw dot already?     */
  416. X            break;            /* Exit loop, two dots    */
  417. X        dotflag = TRUE;         /* Remember the dot    */
  418. X        radix = 10;            /* Decimal fraction    */
  419. X        }
  420. X        else if (c == '+' || c == '-') {    /* 1.0e+10              */
  421. X        if (signseen)                   /* Sign in wrong place? */
  422. X            break;            /* Exit loop, not nbr.    */
  423. X        /* signseen = TRUE; */        /* Remember we saw it    */
  424. X        }
  425. X        else {                /* Check the digit    */
  426. X        switch (c) {
  427. X        case '8': case '9':             /* Sometimes wrong      */
  428. X            octal89 = TRUE;        /* Do check later    */
  429. X        case '0': case '1': case '2': case '3':
  430. X        case '4': case '5': case '6': case '7':
  431. X            break;            /* Always ok        */
  432. X
  433. X        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  434. X        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  435. X            if (radix == 16)            /* Alpha's are ok only  */
  436. X            break;            /* if reading hex.    */
  437. X        default:            /* At number end    */
  438. X            goto done;            /* Break from for loop    */
  439. X        }                /* End of switch    */
  440. X        }                    /* End general case    */
  441. X        (*outfun)(c);                       /* Accept the character */
  442. X        signseen = TRUE;            /* Don't read sign now  */
  443. X        c = get();                          /* Read another char    */
  444. X    }                    /* End of scan loop    */
  445. X    /*
  446. X     * When we break out of the scan loop, c contains the first
  447. X     * character (maybe) not in the number.  If the number is an
  448. X     * integer, allow a trailing 'L' for long and/or a trailing 'U'
  449. X     * for unsigned.  If not those, push the trailing character back
  450. X     * on the input stream.  Floating point numbers accept a trailing
  451. X     * 'L' for "long double".
  452. X     */
  453. Xdone:    if (dotflag || expseen) {               /* Floating point?      */
  454. X        if (c == 'l' || c == 'L') {
  455. X        (*outfun)(c);
  456. X        c = get();                      /* Ungotten later       */
  457. X        }
  458. X    }
  459. X    else {                    /* Else it's an integer */
  460. X        /*
  461. X         * We know that dotflag and expseen are both zero, now:
  462. X         * dotflag signals "saw 'L'", and
  463. X         * expseen signals "saw 'U'".
  464. X         */
  465. X        for (;;) {
  466. X        switch (c) {
  467. X        case 'l':
  468. X        case 'L':
  469. X            if (dotflag)
  470. X            goto nomore;
  471. X            dotflag = TRUE;
  472. X            break;
  473. X
  474. X        case 'u':
  475. X        case 'U':
  476. X            if (expseen)
  477. X            goto nomore;
  478. X            expseen = TRUE;
  479. X            break;
  480. X
  481. X        default:
  482. X            goto nomore;
  483. X        }
  484. X        (*outfun)(c);                   /* Got 'L' or 'U'.      */
  485. X        c = get();                      /* Look at next, too.   */
  486. X        }
  487. X    }
  488. Xnomore: unget();                                /* Not part of a number */
  489. X    if (octal89 && radix == 8)
  490. X        cwarn("Illegal digit in octal number", NULLST);
  491. X    DBUG_VOID_RETURN;
  492. X}
  493. X
  494. Xsave(c)
  495. Xregister int    c;
  496. X{
  497. X    if (workp >= &work[NWORK])
  498. X        cfatal("Work buffer overflow", NULLST);
  499. X    else *workp++ = c;
  500. X}
  501. X
  502. Xchar *
  503. Xsavestring(text)
  504. Xchar        *text;
  505. X/*
  506. X * Store a string into free memory.
  507. X */
  508. X{
  509. X    register char    *result;
  510. X
  511. X    DBUG_ENTER ("savestring");
  512. X    result = getmem(strlen(text) + 1);
  513. X    strcpy(result, text);
  514. X    DBUG_RETURN (result);
  515. X}
  516. X
  517. XFILEINFO    *
  518. Xgetfile(bufsize, name)
  519. Xint        bufsize;        /* Line or define buffer size    */
  520. Xchar        *name;            /* File or macro name string    */
  521. X/*
  522. X * Common FILEINFO buffer initialization for a new file or macro.
  523. X */
  524. X{
  525. X    register FILEINFO    *file;
  526. X    register int        size;
  527. X
  528. X    DBUG_ENTER ("getfile");
  529. X    size = strlen(name);                    /* File/macro name      */
  530. X    file = (FILEINFO *) getmem((int)(sizeof (FILEINFO) + bufsize + size));
  531. X    file->parent = infile;            /* Chain files together */
  532. X    file->fp = NULL;            /* No file yet        */
  533. X    file->filename = savestring(name);      /* Save file/macro name */
  534. X    file->progname = NULL;            /* No #line seen yet    */
  535. X    file->unrecur = 0;            /* No macro fixup    */
  536. X    file->bptr = file->buffer;        /* Initialize line ptr    */
  537. X    file->buffer[0] = EOS;            /* Force first read    */
  538. X    file->line = 0;             /* (Not used just yet)  */
  539. X    if (infile != NULL)                     /* If #include file     */
  540. X        infile->line = line;        /* Save current line    */
  541. X    infile = file;                /* New current file    */
  542. X    line = 1;                /* Note first line    */
  543. X    DBUG_RETURN (file);                     /* All done.            */
  544. X}
  545. X
  546. Xchar *
  547. Xgetmem(size)
  548. Xint        size;
  549. X/*
  550. X * Get a block of free memory.
  551. X */
  552. X{
  553. X    register char    *result;
  554. X    extern char    *malloc();
  555. X
  556. X    DBUG_ENTER ("getmem");
  557. X    if ((result = malloc((unsigned) size)) == NULL)
  558. X        cfatal("Out of memory", NULLST);
  559. X    DBUG_RETURN (result);
  560. X}
  561. X
  562. X#ifndef amiga
  563. Xchar *
  564. Xincmem(obj,size)
  565. Xchar        *obj;
  566. Xint        size;
  567. X/*
  568. X * Get a block of free memory.
  569. X */
  570. X{
  571. X    register char    *result;
  572. X    extern char    *realloc();
  573. X
  574. X    DBUG_ENTER ("incmem");
  575. X    if ((result = realloc(obj, (unsigned) size)) == NULL)
  576. X        cfatal("Out of memory", NULLST);
  577. X    DBUG_RETURN (result);
  578. X}
  579. X#endif /* amiga */
  580. X
  581. X/*
  582. X *            C P P    S y m b o l   T a b l e s
  583. X */
  584. X
  585. X/*
  586. X * SBSIZE defines the number of hash-table slots for the symbol table.
  587. X * It must be a power of 2.
  588. X */
  589. X#ifndef SBSIZE
  590. X#define SBSIZE    64
  591. X#endif
  592. X#define SBMASK    (SBSIZE - 1)
  593. X#if (SBSIZE ^ SBMASK) != ((SBSIZE * 2) - 1)
  594. X    << error, SBSIZE must be a power of 2 >>
  595. X#endif
  596. X
  597. Xstatic DEFBUF    *symtab[SBSIZE];    /* Symbol table queue headers    */
  598. X
  599. XDEFBUF *
  600. Xlookid(c)
  601. Xint    c;                /* First character of token    */
  602. X/*
  603. X * Look for the next token in the symbol table.  Returns token in tokenbuf.
  604. X * If found, returns the table pointer;  Else returns NULL.
  605. X */
  606. X{
  607. X    register int        nhash;
  608. X    register DEFBUF     *dp;
  609. X    register int        ct;
  610. X    int            temp;
  611. X    int            isrecurse;    /* For #define foo foo    */
  612. X
  613. X    DBUG_ENTER ("lookid");
  614. X    nhash = 0;
  615. X    if ((isrecurse = (c == DEF_MAGIC)))     /* If recursive macro   */
  616. X        c = get();                          /* hack, skip DEF_MAGIC */
  617. X    ct = 0;
  618. X    do
  619. X      {
  620. X        if (ct == tokenbsize)
  621. X#ifdef amiga
  622. X        /*
  623. X         * Duplicate the action of incmem, which grows the area
  624. X         * to the new size, reallocating and copying if necessary.
  625. X         * The disadvantage of this emulation is that the copy is
  626. X         * always done because we have no realloc().
  627. X         */
  628. X          {
  629. X         extern char *malloc ();
  630. X         extern char *memcpy ();
  631. X         char *new = malloc ((unsigned) (1 + (tokenbsize *= 2)));
  632. X         if (new == NULL) {
  633. X            cfatal("Out of memory", NULLST);
  634. X         } else {
  635. X            memcpy (new, tokenbuf, ct);
  636. X            free (tokenbuf);
  637. X            tokenbuf = new;
  638. X         }
  639. X          }
  640. X#else
  641. X          tokenbuf = incmem(tokenbuf, 1 + (tokenbsize *= 2));
  642. X#endif
  643. X        tokenbuf[ct++] = c;     /* Store token byte    */
  644. X        nhash += c;         /* Update hash value    */
  645. X        c = get();
  646. X      }
  647. X    while (type[c] == LET || type[c] == DIG);
  648. X    unget();                                /* Rescan terminator    */
  649. X    tokenbuf[ct] = EOS;            /* Terminate token    */
  650. X    if (isrecurse)                          /* Recursive definition */
  651. X        DBUG_RETURN (NULL);                 /* undefined just now   */
  652. X    nhash += ct;                /* Fix hash value    */
  653. X    dp = symtab[nhash & SBMASK];        /* Starting bucket    */
  654. X    while (dp != (DEFBUF *) NULL) {         /* Search symbol table  */
  655. X        if (dp->hash == nhash               /* Fast precheck        */
  656. X         && (temp = strcmp(dp->name, tokenbuf)) >= 0)
  657. X        break;
  658. X        dp = dp->link;            /* Nope, try next one    */
  659. X    }
  660. X    DBUG_RETURN ((temp == 0) ? dp : NULL);
  661. X}
  662. X
  663. XDEFBUF *
  664. Xdefendel(name, delete)
  665. Xchar        *name;
  666. Xint        delete;         /* TRUE to delete a symbol    */
  667. X/*
  668. X * Enter this name in the lookup table (delete = FALSE)
  669. X * or delete this name (delete = TRUE).
  670. X * Returns a pointer to the define block (delete = FALSE)
  671. X * Returns NULL if the symbol wasn't defined (delete = TRUE).
  672. X */
  673. X{
  674. X    register DEFBUF     *dp;
  675. X    register DEFBUF     **prevp;
  676. X    register char        *np;
  677. X    int            nhash;
  678. X    int            temp;
  679. X    int            size;
  680. X
  681. X    DBUG_ENTER ("defendel");
  682. X    for (nhash = 0, np = name; *np != EOS;)
  683. X        nhash += *np++;
  684. X    size = (np - name);
  685. X    nhash += size;
  686. X    prevp = &symtab[nhash & SBMASK];
  687. X    while ((dp = *prevp) != (DEFBUF *) NULL) {
  688. X        if (dp->hash == nhash
  689. X         && (temp = strcmp(dp->name, name)) >= 0) {
  690. X        if (temp > 0)
  691. X            dp = NULL;            /* Not found        */
  692. X        else {
  693. X            *prevp = dp->link;        /* Found, unlink and    */
  694. X            if (dp->repl != NULL)       /* Free the replacement */
  695. X            free(dp->repl);         /* if any, and then     */
  696. X            free((char *) dp);          /* Free the symbol      */
  697. X        }
  698. X        break;
  699. X        }
  700. X        prevp = &dp->link;
  701. X    }
  702. X    if (!delete) {
  703. X        dp = (DEFBUF *) getmem((int) (sizeof (DEFBUF) + size));
  704. X        dp->link = *prevp;
  705. X        *prevp = dp;
  706. X        dp->hash = nhash;
  707. X        dp->repl = NULL;
  708. X        dp->nargs = 0;
  709. X        strcpy(dp->name, name);
  710. X    }
  711. X    DBUG_RETURN (dp);
  712. X}
  713. X
  714. X#if DEBUG
  715. X
  716. Xdumpdef(why)
  717. Xchar        *why;
  718. X{
  719. X    register DEFBUF     *dp;
  720. X    register DEFBUF     **syp;
  721. X
  722. X    DBUG_ENTER ("dumpdef");
  723. X    printf("CPP symbol table dump %s\n", why);
  724. X    for (syp = symtab; syp < &symtab[SBSIZE]; syp++) {
  725. X        if ((dp = *syp) != (DEFBUF *) NULL) {
  726. X        printf("symtab[%d]\n", (syp - symtab));
  727. X        do {
  728. X            dumpadef((char *) NULL, dp);
  729. X        } while ((dp = dp->link) != (DEFBUF *) NULL);
  730. X        }
  731. X    }
  732. X    DBUG_VOID_RETURN;
  733. X}
  734. X
  735. Xdumpadef(why, dp)
  736. Xchar        *why;            /* Notation            */
  737. Xregister DEFBUF *dp;
  738. X{
  739. X    register char        *cp;
  740. X    register int        c;
  741. X
  742. X    DBUG_ENTER ("dumpadef");
  743. X    printf(" \"%s\" [%d]", dp->name, dp->nargs);
  744. X    if (why != NULL)
  745. X        printf(" (%s)", why);
  746. X    if (dp->repl != NULL) {
  747. X        printf(" => ");
  748. X        for (cp = dp->repl; (c = *cp++ & 0xFF) != EOS;) {
  749. X        if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC))
  750. X            printf("<%d>", c - MAC_PARM);
  751. X        else if (isprint(c) || c == '\n' || c == '\t')
  752. X            putchar(c);
  753. X        else if (c < ' ')
  754. X            printf("<^%c>", c + '@');
  755. X        else
  756. X            printf("<\\0%o>", c);
  757. X        }
  758. X    }
  759. X    else {
  760. X        printf(", no replacement.");
  761. X    }
  762. X    putchar('\n');
  763. X    DBUG_VOID_RETURN;
  764. X}
  765. X#endif
  766. X
  767. Xoutdefines()
  768. X{
  769. X    register DEFBUF     *dp;
  770. X    register DEFBUF     **syp;
  771. X
  772. X    DBUG_ENTER ("outdefines");
  773. X    deldefines();                   /* Delete built-in #defines     */
  774. X    for (syp = symtab; syp < &symtab[SBSIZE]; syp++) {
  775. X        if ((dp = *syp) != (DEFBUF *) NULL) {
  776. X        do {
  777. X            outadefine(dp);
  778. X        } while ((dp = dp->link) != (DEFBUF *) NULL);
  779. X        }
  780. X    }
  781. X    DBUG_VOID_RETURN;
  782. X}
  783. X
  784. Xoutadefine(dp)
  785. Xregister DEFBUF *dp;
  786. X{
  787. X    register char        *cp;
  788. X    register int        c;
  789. X
  790. X    DBUG_ENTER ("outadefine");
  791. X    printf("#define %s", dp->name);
  792. X    if (dp->nargs > 0) {
  793. X        register int i;
  794. X        printf("(");
  795. X        for (i = 1; i < dp->nargs; i++) {
  796. X        printf("__%d,", i);
  797. X        }
  798. X        printf("__%d)", i);
  799. X    } else if (dp->nargs == 0) {
  800. X        printf("()");
  801. X    }
  802. X    if (dp->repl != NULL) {
  803. X        printf("\t");
  804. X        for (cp = dp->repl; (c = *cp++ & 0xFF) != EOS;) {
  805. X        if (c >= MAC_PARM && c < (MAC_PARM + PAR_MAC))
  806. X            printf("__%d", c - MAC_PARM + 1);
  807. X        else if (isprint(c) || c == '\t' || c == '\n')
  808. X            putchar(c);
  809. X        else switch (c) {
  810. X        case QUOTE_PARM:
  811. X            printf("#");
  812. X            break;
  813. X        case DEF_MAGIC:         /* Special anti-recursion */
  814. X        case MAC_PARM + PAR_MAC:    /* Special "arg" marker */
  815. X            break;
  816. X        case COM_SEP:
  817. X#if COMMENT_INVISIBLE
  818. X            printf("/**/");
  819. X#else
  820. X            printf(" ");
  821. X#endif
  822. X            break;
  823. X        case TOK_SEP:
  824. X            printf("##");
  825. X            break;
  826. X        default:
  827. X            printf("\\0%o", c);
  828. X        }
  829. X        }
  830. X    }
  831. X    putchar('\n');
  832. X    DBUG_VOID_RETURN;
  833. X}
  834. X
  835. X/*
  836. X *            G E T
  837. X */
  838. X
  839. Xint
  840. Xget()
  841. X/*
  842. X * Return the next character from a macro or the current file.
  843. X * Handle end of file from #include files.
  844. X */
  845. X{
  846. X    register int        c;
  847. X    register FILEINFO    *file;
  848. X    register int        popped;     /* Recursion fixup    */
  849. X    extern char        *fgets ();
  850. X
  851. X    DBUG_ENTER ("get");
  852. X    popped = 0;
  853. Xget_from_file:
  854. X    if ((file = infile) == NULL)
  855. X        DBUG_RETURN (EOF_CHAR);
  856. Xnewline:
  857. X#if 0
  858. X    printf("get(%s), recursion %d, line %d, bptr = %d, buffer \"%s\"\n",
  859. X        file->filename, recursion, line,
  860. X        file->bptr - file->buffer, file->buffer);
  861. X#endif
  862. X    /*
  863. X     * Read a character from the current input line or macro.
  864. X     * At EOS, either finish the current macro (freeing temp.
  865. X     * storage) or read another line from the current input file.
  866. X     * At EOF, exit the current file (#include) or, at EOF from
  867. X     * the cpp input file, return EOF_CHAR to finish processing.
  868. X     */
  869. X    if ((c = *file->bptr++ & 0xFF) == EOS) {
  870. X        /*
  871. X         * Nothing in current line or macro.  Get next line (if
  872. X         * input from a file), or do end of file/macro processing.
  873. X         * In the latter case, jump back to restart from the top.
  874. X         */
  875. X        if (file->fp == NULL) {             /* NULL if macro        */
  876. X        popped++;
  877. X        recursion -= file->unrecur;
  878. X        if (recursion < 0)
  879. X            recursion = 0;
  880. X        infile = file->parent;        /* Unwind file chain    */
  881. X        }
  882. X        else {                /* Else get from a file */
  883. X        if ((file->bptr = fgets(file->buffer, NBUFF, file->fp))
  884. X            != NULL) {
  885. X#if DEBUG
  886. X            if (debug > 1) {            /* Dump it to stdout    */
  887. X            printf("\n#line %d (%s), %s",
  888. X                line, file->filename, file->buffer);
  889. X            }
  890. X#endif
  891. X            goto newline;        /* process the line    */
  892. X        }
  893. X        else {
  894. X            fclose(file->fp);           /* Close finished file  */
  895. X            if ((infile = file->parent) != NULL) {
  896. X            /*
  897. X             * There is an "ungotten" newline in the current
  898. X             * infile buffer (set there by doinclude() in
  899. X             * cpp1.c).  Thus, we know that the mainline code
  900. X             * is skipping over blank lines and will do a
  901. X             * #line at its convenience.
  902. X             */
  903. X            wrongline = TRUE;    /* Need a #line now    */
  904. X            }
  905. X        }
  906. X        }
  907. X        /*
  908. X         * Free up space used by the (finished) file or macro and
  909. X         * restart input from the parent file/macro, if any.
  910. X         */
  911. X        free(file->filename);               /* Free name and        */
  912. X        if (file->progname != NULL)         /* if a #line was seen, */
  913. X        free(file->progname);           /* free it, too.        */
  914. X        free((char *) file);                /* Free file space      */
  915. X        if (infile == NULL)                 /* If at end of file    */
  916. X        DBUG_RETURN (EOF_CHAR);         /* Return end of file   */
  917. X        line = infile->line;        /* Reset line number    */
  918. X        goto get_from_file;         /* Get from the top.    */
  919. X    }
  920. X    /*
  921. X     * Common processing for the new character.
  922. X     */
  923. X    if (c == DEF_MAGIC && file->fp != NULL) /* Don't allow delete   */
  924. X        goto newline;            /* from a file        */
  925. X    if (file->parent != NULL) {             /* Macro or #include    */
  926. X        if (popped != 0)
  927. X        file->parent->unrecur += popped;
  928. X        else {
  929. X        recursion -= file->parent->unrecur;
  930. X        if (recursion < 0)
  931. X            recursion = 0;
  932. X        file->parent->unrecur = 0;
  933. X        }
  934. X    }
  935. X    if (c == '\n')                          /* Maintain current     */
  936. X        ++line;                /* line counter     */
  937. X    if (instring)                           /* Strings just return  */
  938. X        DBUG_RETURN (c);                    /* the character.       */
  939. X    else if (c == '/') {                    /* Comment?             */
  940. X        instring = TRUE;            /* So get() won't loop  */
  941. X        if ((c = get()) != '*') {           /* Next byte '*'?       */
  942. X        instring = FALSE;        /* Nope, no comment    */
  943. X        unget();                        /* Push the char. back  */
  944. X        DBUG_RETURN ('/');              /* Return the slash     */
  945. X        }
  946. X        if (keepcomments) {                 /* If writing comments  */
  947. X        putchar('/');                   /* Write out the        */
  948. X        putchar('*');                   /*   initializer        */
  949. X        }
  950. X        for (;;) {                          /* Eat a comment        */
  951. X        c = get();
  952. Xtest:        if (keepcomments && c != EOF_CHAR)
  953. X            cput(c);
  954. X        switch (c) {
  955. X        case EOF_CHAR:
  956. X            cerror("EOF in comment", NULLST);
  957. X            DBUG_RETURN (EOF_CHAR);
  958. X
  959. X#ifdef NOTDEF
  960. X        case '/':
  961. X            if ((c = get()) != '*')     /* Don't let comments   */
  962. X            goto test;        /* Nest.        */
  963. X            cwarn("Nested comments", NULLST);
  964. X#endif /* NOTDEF */
  965. X                        /* Fall into * stuff    */
  966. X        case '*':
  967. X            if ((c = get()) != '/')     /* If comment doesn't   */
  968. X            goto test;        /* end, look at next    */
  969. X            instring = FALSE;        /* End of comment,    */
  970. X            if (keepcomments) {         /* Put out the comment  */
  971. X            cput(c);                /* terminator, too      */
  972. X            }
  973. X            /*
  974. X             * A comment is syntactically "whitespace" --
  975. X             * however, there are certain strange sequences
  976. X             * such as
  977. X             *        #define foo(x)  (something)
  978. X             *            foo|* comment *|(123)
  979. X             *         these are '/' ^           ^
  980. X             * where just returning space (or COM_SEP) will cause
  981. X             * problems.  This can be "fixed" by overwriting the
  982. X             * '/' in the input line buffer with ' ' (or COM_SEP)
  983. X             * but that may mess up an error message.
  984. X             * So, we peek ahead -- if the next character is
  985. X             * "whitespace" we just get another character, if not,
  986. X             * we modify the buffer.  All in the name of purity.
  987. X             */
  988. X            if (*file->bptr == '\n'
  989. X             || type[*file->bptr & 0xFF] == SPA)
  990. X            goto newline;
  991. X#if COMMENT_INVISIBLE
  992. X            /*
  993. X             * Return magic (old-fashioned) syntactic space.
  994. X             */
  995. X            DBUG_RETURN ((file->bptr[-1] = COM_SEP));
  996. X#else
  997. X            DBUG_RETURN ((file->bptr[-1] = ' '));
  998. X#endif
  999. X
  1000. X        case '\n':                      /* we'll need a #line   */
  1001. X            if (!keepcomments)
  1002. X            wrongline = TRUE;    /* later...        */
  1003. X        default:            /* Anything else is    */
  1004. X            break;            /* Just a character    */
  1005. X        }                /* End switch        */
  1006. X        }                    /* End comment loop    */
  1007. X    }                    /* End if in comment    */
  1008. X    else if (!inmacro && c == '\\') {       /* If backslash, peek   */
  1009. X        if ((c = get()) == '\n') {          /* for a <nl>.  If so,  */
  1010. X        wrongline = TRUE;
  1011. X        goto newline;
  1012. X        }
  1013. X        else {                /* Backslash anything    */
  1014. X        unget();                        /* Get it later         */
  1015. X        DBUG_RETURN ('\\');             /* Return the backslash */
  1016. X        }
  1017. X    }
  1018. X    else if (c == '\f' || c == VT)          /* Form Feed, Vertical  */
  1019. X        c = ' ';                            /* Tab are whitespace   */
  1020. X    DBUG_RETURN (c);                        /* Just return the char */
  1021. X}
  1022. X
  1023. Xunget()
  1024. X/*
  1025. X * Backup the pointer to reread the last character.  Fatal error
  1026. X * (code bug) if we backup too far.  unget() may be called,
  1027. X * without problems, at end of file.  Only one character may
  1028. X * be ungotten.  If you need to unget more, call ungetstring().
  1029. X */
  1030. X{
  1031. X    register FILEINFO    *file;
  1032. X
  1033. X    DBUG_ENTER ("unget");
  1034. X    if ((file = infile) == NULL)
  1035. X        DBUG_VOID_RETURN;        /* Unget after EOF        */
  1036. X    if (--file->bptr < file->buffer)
  1037. X        cfatal("Too much pushback", NULLST);
  1038. X    if (*file->bptr == '\n')        /* Ungetting a newline?         */
  1039. X        --line;            /* Unget the line number, too    */
  1040. X    DBUG_VOID_RETURN;
  1041. X}
  1042. X
  1043. Xungetstring(text)
  1044. Xchar        *text;
  1045. X/*
  1046. X * Push a string back on the input stream.  This is done by treating
  1047. X * the text as if it were a macro.
  1048. X */
  1049. X{
  1050. X    register FILEINFO    *file;
  1051. X    extern FILEINFO     *getfile();
  1052. X
  1053. X    DBUG_ENTER ("ungetstring");
  1054. X    file = getfile(strlen(text) + 1, "");
  1055. X    strcpy(file->buffer, text);
  1056. X    DBUG_VOID_RETURN;
  1057. X}
  1058. X
  1059. Xint
  1060. Xcget()
  1061. X/*
  1062. X * Get one character, absorb "funny space" after comments or
  1063. X * token concatenation
  1064. X */
  1065. X{
  1066. X    register int    c;
  1067. X
  1068. X    DBUG_ENTER ("cget");
  1069. X    do {
  1070. X        c = get();
  1071. X#if COMMENT_INVISIBLE
  1072. X    } while (c == TOK_SEP || c == COM_SEP);
  1073. X#else
  1074. X    } while (c == TOK_SEP);
  1075. X#endif
  1076. X    DBUG_RETURN (c);
  1077. X}
  1078. X
  1079. X/*
  1080. X * Error messages and other hacks.  The first byte of severity
  1081. X * is 'S' for string arguments and 'I' for int arguments.  This
  1082. X * is needed for portability with machines that have int's that
  1083. X * are shorter than  char *'s.
  1084. X */
  1085. X
  1086. Xstatic
  1087. Xdomsg(severity, format, arg)
  1088. Xchar        *severity;        /* "Error", "Warning", "Fatal"  */
  1089. Xchar        *format;        /* Format for the error message */
  1090. Xchar        *arg;            /* Something for the message    */
  1091. X/*
  1092. X * Print filenames, macro names, and line numbers for error messages.
  1093. X */
  1094. X{
  1095. X    register char        *tp;
  1096. X    register FILEINFO    *file;
  1097. X
  1098. X    DBUG_ENTER ("domsg");
  1099. X    for (file = infile; file && !file->fp; file = file->parent)
  1100. X      ;
  1101. X    tp = file ? file->filename : 0;
  1102. X    fprintf (stderr, "%s\"%s\", line %d: %s: ",
  1103. X         MSG_PREFIX, tp, line, &severity[1]);
  1104. X    if (*severity == 'S')
  1105. X      fprintf(stderr, format, arg);
  1106. X    else
  1107. X      fprintf(stderr, format, (int) arg);
  1108. X    putc('\n', stderr);
  1109. X
  1110. X    if (file)   /*OIS*0.92*/
  1111. X    while ((file = file->parent) != NULL) { /* Print #includes, too */
  1112. X        tp = file->parent ? "," : ".";
  1113. X        if (file->fp == NULL)
  1114. X        fprintf(stderr, " from macro %s%s\n", file->filename, tp);
  1115. X        else {
  1116. X        fprintf(stderr, " from file %s, line %d%s\n",
  1117. X            (file->progname != NULL)
  1118. X            ? file->progname : file->filename,
  1119. X            file->line, tp);
  1120. X        }
  1121. X    }
  1122. X    DBUG_VOID_RETURN;
  1123. X}
  1124. X
  1125. Xcerror(format, sarg)
  1126. Xchar        *format;
  1127. Xchar        *sarg;        /* Single string argument        */
  1128. X/*
  1129. X * Print a normal error message, string argument.
  1130. X */
  1131. X{
  1132. X    DBUG_ENTER ("cerror");
  1133. X    domsg("SError", format, sarg);
  1134. X    errors++;
  1135. X    DBUG_VOID_RETURN;
  1136. X}
  1137. X
  1138. Xcierror(format, narg)
  1139. Xchar        *format;
  1140. Xint        narg;        /* Single numeric argument        */
  1141. X/*
  1142. X * Print a normal error message, numeric argument.
  1143. X */
  1144. X{
  1145. X    DBUG_ENTER ("cierror");
  1146. X    domsg("IError", format, (char *) narg);
  1147. X    errors++;
  1148. X    DBUG_VOID_RETURN;
  1149. X}
  1150. X
  1151. Xcfatal(format, sarg)
  1152. Xchar        *format;
  1153. Xchar        *sarg;            /* Single string argument    */
  1154. X/*
  1155. X * A real disaster
  1156. X */
  1157. X{
  1158. X    DBUG_ENTER ("cfatal");
  1159. X    domsg("SFatal error", format, sarg);
  1160. X    exit(IO_ERROR);
  1161. X    DBUG_VOID_RETURN;
  1162. X}
  1163. X
  1164. Xcwarn(format, sarg)
  1165. Xchar        *format;
  1166. Xchar        *sarg;            /* Single string argument    */
  1167. X/*
  1168. X * A non-fatal error, string argument.
  1169. X */
  1170. X{
  1171. X    DBUG_ENTER ("cwarn");
  1172. X    domsg("SWarning", format, sarg);
  1173. X    DBUG_VOID_RETURN;
  1174. X}
  1175. X
  1176. Xciwarn(format, narg)
  1177. Xchar        *format;
  1178. Xint        narg;            /* Single numeric argument    */
  1179. X/*
  1180. X * A non-fatal error, numeric argument.
  1181. X */
  1182. X{
  1183. X    DBUG_ENTER ("ciwarn");
  1184. X    domsg("IWarning", format, (char *) narg);
  1185. X    DBUG_VOID_RETURN;
  1186. X}
  1187. X
  1188. X#if amiga
  1189. X
  1190. Xchar *memcpy (s1, s2, n)
  1191. Xchar *s1, *s2;
  1192. Xint n;
  1193. X{
  1194. X    char *saves1 = s1;
  1195. X
  1196. X    DBUG_ENTER ("memcpy");
  1197. X    while (n-- > 0) {
  1198. X        *s1++ = *s2++;
  1199. X    }
  1200. X    DBUG_RETURN (saves1);
  1201. X}
  1202. X
  1203. X#endif /* amiga */
  1204. END_OF_FILE
  1205. if test 33823 -ne `wc -c <'Cpp6.c'`; then
  1206.     echo shar: \"'Cpp6.c'\" unpacked with wrong size!
  1207. fi
  1208. # end of 'Cpp6.c'
  1209. fi
  1210. echo shar: End of archive 5 \(of 5\).
  1211. cp /dev/null ark5isdone
  1212. MISSING=""
  1213. for I in 1 2 3 4 5 ; do
  1214.     if test ! -f ark${I}isdone ; then
  1215.     MISSING="${MISSING} ${I}"
  1216.     fi
  1217. done
  1218. if test "${MISSING}" = "" ; then
  1219.     echo You have unpacked all 5 archives.
  1220.     rm -f ark[1-9]isdone
  1221. else
  1222.     echo You still need to unpack the following archives:
  1223.     echo "        " ${MISSING}
  1224. fi
  1225. ##  End of shell archive.
  1226. exit 0
  1227. -- 
  1228. Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
  1229.     amiga@cs.odu.edu    
  1230. or    amiga@xanth.cs.odu.edu    ( obsolescent mailers may need this address )
  1231. or    ...!uunet!xanth!amiga    ( very obsolescent mailers need this address )
  1232.  
  1233. Comments, questions, and suggestions s should be addressed to ``amiga-request''
  1234. (only use ``amiga'' for submissions) at the above addresses.
  1235.